/**
 * 
 */
package cn.edu.nju.ws.sview.wyge.relations.datasets;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;

import com.hp.hpl.jena.rdf.model.ResourceF;

import cn.edu.nju.ws.sview.Config;
import cn.edu.nju.ws.sview.cache.URIIDCache;
import cn.edu.nju.ws.sview.cache.URILabelCache;
import cn.edu.nju.ws.sview.cache.UserNameIDCache;
import cn.edu.nju.ws.sview.database.DBConnectionFactory;
import cn.edu.nju.ws.sview.database.DBOperations;
import cn.edu.nju.ws.sview.rdf.ResourceFactory;
import cn.edu.nju.ws.sview.rdf.URIResource;
import cn.edu.nju.ws.sview.util.PropertyList;
import cn.edu.nju.ws.sview.wyge.relations.adataset.comment.DatasetComment;
import cn.edu.nju.ws.sview.wyge.relations.adataset.entities.GetNamedEntities;
import cn.edu.nju.ws.sview.wyge.relations.adataset.entities.ISentence;
import cn.edu.nju.ws.sview.wyge.relations.adataset.entities.SnippetDisplay;
import cn.edu.nju.ws.sview.wyge.util.Util;

/**
 * @author Weiyi Ge (geweiyi@gmail.com) 2012-7-19
 * @author Qingxia Liu
 *
 */
public class DatasetItem {
	private String ds_type;//custom or uri
	private int id;
	private String uri = null;
	private String showName = null;//usually for bookmark show//bookmarkName = null;
	private int groupId=-1;//===
	
//	private ArrayList<DatasetComment> descriptions = null;//[0] description [1] language [[2] id]
	public final static String CUSTOM_GENRE = "custom";
	public final static String URI_GENRE = "uri";
	public final static String TEMP_GENRE = "temp";
	public final static String CUSTOM_DATASET_URI_PREFIX;
	
	public final static int URI_INT ;//= 11;
	public final static int CUSTOM_INT ;//= 12;
	//for visit
	public final static int UNVISITED = 0;
	public final static int VISITED_COUNT_VALID = 1;
	public final static int VISITED_COUNT_INVALID = 2;	

	static{
		CUSTOM_DATASET_URI_PREFIX = ResourceFactory.CUSTOM_FACET_URI_PREFIX+"dataset/c";//======
		
		Properties properties = new Properties();
		try {
			properties.load(DatasetItem.class.getClassLoader().getResourceAsStream("conf.properties")) ;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		URI_INT = Integer.parseInt(properties.getProperty("uri_dataset"));
		CUSTOM_INT = Integer.parseInt(properties.getProperty("custom_dataset"));
		properties.clear();
	}

	public static void main(String[] args){
//		DatasetItem ds = new DatasetItem("custom",8,null);
//		System.out.println(ds.getUri());

		DatasetItem ds = new DatasetItem("uri",10851336,null);//10851336,null);
		System.out.println(ds.getUri()+"|"+DatasetItem.getShowNameByDatasetID(ds, "en"));
		
	}
	public DatasetItem(String ds_type, int id, String uri) {
		this.ds_type = ds_type;
		this.id = id;
		this.uri = uri;

		if(uri == null && ds_type.contentEquals(CUSTOM_GENRE)){
			this.uri = CUSTOM_DATASET_URI_PREFIX+id;
			
		}
	}
	public static int datasetTypeToInt(String ds_type){
		if(ds_type.contentEquals(DatasetItem.URI_GENRE)){
			return 11;
		}else if(ds_type.contentEquals(DatasetItem.CUSTOM_GENRE)){
			return 12;
		}else if(ds_type.contentEquals(DatasetItem.TEMP_GENRE)){
			return 13;
		}else{
			return -1;
		}
	}
	public static String datasetIntToType(int ds_type_int){
		if(ds_type_int == DatasetItem.URI_INT){
			return DatasetItem.URI_GENRE;
		}else if(ds_type_int == DatasetItem.CUSTOM_INT){
			return DatasetItem.CUSTOM_GENRE;
		}else{
			return "";
		}
	}
	/**
	 * for visit record
	 * @param userID
	 * @param ds_type
	 * @param datasetID
	 * @param lang
	 */
	public static void storeUserVisit(int userID,String ds_type,int datasetID, String lang){
		int ds_type_int = datasetTypeToInt(ds_type);
			int status = checkStatus(userID, ds_type_int, datasetID) ;
			if(status == DatasetItem.UNVISITED){
				 Connection con = DBConnectionFactory.getConnection();
				 try {
					 PreparedStatement delstmt = con.prepareStatement("delete from user_day_visit_control where user_id=? and member_type=? and member_id=?");
					 delstmt.setInt(1, userID);
					 delstmt.setInt(2, ds_type_int) ;
					 delstmt.setInt(3, datasetID) ;
					 delstmt.executeUpdate();
					 delstmt.close();
					 PreparedStatement stmt = con.prepareStatement("insert into user_day_visit_control(user_id,member_type,member_id,date,control_type) values(?,?,?,NOW(),'dataset')");
					   stmt.setInt(1, userID);
					   stmt.setInt(2, ds_type_int) ;
					   stmt.setInt(3, datasetID) ;
					   stmt.executeUpdate() ;
					   stmt.close();
					   con.close();
					   userVisit(userID,ds_type_int,datasetID,lang);
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
				}
				
			}else if(status==DatasetItem.VISITED_COUNT_INVALID){
				return ;
			}else if(status==DatasetItem.VISITED_COUNT_VALID){
				 Connection con = DBConnectionFactory.getConnection();
				 try {
					   PreparedStatement stmt = con.prepareStatement(
							   "update user_day_visit_control set date=? where user_id=? and member_type=? and member_id=?");
					   stmt.setDate(1, new java.sql.Date(new Date().getTime()));
					   stmt.setInt(2, userID);
					   stmt.setInt(3, ds_type_int) ;
					   stmt.setInt(4, datasetID) ;
					   stmt.executeUpdate() ;
					   stmt.close();
					   con.close();
					   userVisit(userID,ds_type_int,datasetID,lang);
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
				}
				
			}
	}
	 /**
	    * 检查用户当天访问该实体的状态,判断是否可以计数
	    * @return
	    */
	   private static int checkStatus(int userID,int ds_type_int,int datasetID){
		     int status  = DatasetItem.UNVISITED;
			 Connection con = DBConnectionFactory.getConnection();
			 try {
				    Statement stmt = con.createStatement();
				    ResultSet rs = stmt.executeQuery(
				        String.format("select date from user_day_visit_control where user_id=%d and member_type=%d and member_id=%d", userID,ds_type_int,datasetID)) ;
				    if(rs.next()){
				    	Date date = rs.getTimestamp("date") ;
				    	Date now = new Date();
				    	Calendar c1 =Calendar.getInstance();
				    	Calendar c2 = Calendar.getInstance();
				    	c1.setTime(date) ;
				    	c2.setTime(now) ;
				    	if((c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR))  
				                && (c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH))  
				                && (c1.get(Calendar.DAY_OF_MONTH) == c2.get(Calendar.DAY_OF_MONTH))){
				    		long difference = now.getTime()-date.getTime();
				    		/*discriminate unsigned users*/
				    		if(difference<2*60*60*1000){
				    			status = DatasetItem.VISITED_COUNT_INVALID;
				    		}else
				    			status= DatasetItem.VISITED_COUNT_VALID;
				    	}else{
				    		status= DatasetItem.VISITED_COUNT_VALID;
				    	}
				    }
				    rs.close();
				    stmt.close();
					con.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
			}
			return status;
	   }
	private static void userVisit(int userID,int ds_type_int,int datasetID, String lang){
		   try {
			Connection con = DBConnectionFactory.getConnection();
			int date = Calendar.getInstance().get(Calendar.DAY_OF_WEEK)-1;
			PreparedStatement user_day_visit_stmt = con.prepareStatement(
					"insert into user_day_visit(user_id,member_type,member_id,date,times_recent) " +
					"values(?,?,?,?,?) on duplicate key update times_recent=times_recent+1");
			user_day_visit_stmt.setInt(1, userID) ;
			user_day_visit_stmt.setInt(2, ds_type_int);
			user_day_visit_stmt.setInt(3, datasetID) ;
			int times = 1;
			user_day_visit_stmt.setInt(4,date);
			user_day_visit_stmt.setInt(5, times) ;
			user_day_visit_stmt.executeUpdate();
			user_day_visit_stmt.close();
			
			PreparedStatement user_visit_stmt = con.prepareStatement(
					"insert into user_visit(user_id,member_type,member_id,times_total) " +
					"values(?,?,?,?) on duplicate key update times_total=times_total+1");
			user_visit_stmt.setInt(1, userID) ;
			user_visit_stmt.setInt(2, ds_type_int);
			user_visit_stmt.setInt(3, datasetID) ;
			user_visit_stmt.setInt(4, times) ;
			user_visit_stmt.executeUpdate();
			user_visit_stmt.close();
			
			PreparedStatement visit_lang = con.prepareStatement(
					"insert ignore into visit_lang(member_type,member_id,lang) values(?,?,?)");
			visit_lang.setInt(1,ds_type_int);
			visit_lang.setInt(2,datasetID);
			visit_lang.setString(3,lang);
			visit_lang.executeUpdate();
			visit_lang.close();
			con.close();
			
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		   
	   }		
			
			
	public String getGenre() {
		return ds_type;
	}

	public int getId() {
		return id;
	}
	public String getUri(){
		if(uri == null && ds_type.contentEquals(URI_GENRE)){
			try {
				uri = URIIDCache.getInstance().getURI(id);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return uri;
	}
	
	//=====only for bookmark
	public String getShowName(){
//		if(showName == null){
//			showName = getShowNameByDatasetID(id, ds_type, lang);
//		}
		return this.showName;
	}
	public void setShowName(String showName){
		this.showName = showName;
	}
	//==========================
	public static String getUriLabel(int uid, String lang){
//		System.out.println("ddduid:"+uid+"|lang:"+lang);
		String name = null;
		try {
			String uri = URIIDCache.getInstance().getURI(new Integer(uid));
			name = DBOperations.getLabel(uri,lang);
			if(name==null || name.trim().length()<=0){
				name = URILabelCache.getInstance().getLabel(uid, lang);
				
				if(name.trim().length()==0 && !lang.contentEquals("en")){
					name = URILabelCache.getInstance().getLabel(uid, "en");
				}
				
				if (name.trim().length()==0 && uri!=null) {
					name = Util.getShortenName(uri);
				}
				//=====
				if(name.trim().length() == 0){
//					System.out.println("uid:"+uid+"|lang:"+lang);
					name = URIResource.getLabel(uid, lang);
				}
			}
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return name;
	}
	public static String getShowNameByDatasetID(DatasetItem di, String lang) {
		String name = null;
		String ds_type = di.getGenre();
		int id = di.getId();
		if(ds_type.contentEquals(URI_GENRE)){
			name = getUriLabel(id, lang);
		} else if(ds_type.contentEquals(CUSTOM_GENRE)){
			try {
				Connection conn = DBConnectionFactory.getConnection();
				Statement stmt = conn.createStatement();
				ResultSet rs = stmt.executeQuery(String.format(
						"select name " +
						"from custom_dataset_label " +
						"where custom_dataset_id = %d and lang='%s'", id,lang));
				if ( rs.next() ) {
					name = rs.getString("name") ;
				}
				rs.close();
				
				if(name==null){
					//可能特定语言的名字不存在，拿其它的代替
					rs = stmt.executeQuery(String.format(
							"select name " +
							"from custom_dataset_label " +
							"where custom_dataset_id = %d ", id));
					if(rs.next()){
						name = rs.getString("name");
					}
					rs.close();
				}
				stmt.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		return name;
	}
	/**
	 * get the name of entity of specific lang
	 * @param id. the entity id
	 * @return null if invalid entity id
	 */
	public static String getShowNameByDatasetID(int id,String ds_type, String lang) {
		String name = null;
		if(ds_type.contentEquals(URI_GENRE)){
			name = getUriLabel(id, lang);
		} else if(ds_type.contentEquals(CUSTOM_GENRE)){
			try {
				Connection conn = DBConnectionFactory.getConnection();
				Statement stmt = conn.createStatement();
				ResultSet rs = stmt.executeQuery(String.format(
						"select name " +
						"from custom_dataset_label " +
						"where custom_dataset_id = %d and lang='%s'", id,lang));
				if ( rs.next() ) {
					name = rs.getString("name") ;
				}
				rs.close();
				
				if(name==null){
					//可能特定语言的名字不存在，拿其它的代替
					rs = stmt.executeQuery(String.format(
							"select name " +
							"from custom_dataset_label " +
							"where custom_dataset_id = %d ", id));
					if(rs.next()){
						name = rs.getString("name");
					}
					rs.close();
				}
				stmt.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}else if(ds_type.contentEquals(TEMP_GENRE)){
			name = "Untitled";
			if(lang.contentEquals("zh")){
				name = "未命名";
			}
		}

//		System.out.println("id:"+id+"|"+ds_type+"|"+ds_type.contentEquals(URI_GENRE)+"|name:"+name);
		return name;
	}
//	public String getLabelForShow(String lang){
//		String label = "";
//		DatasetName dn = this.getName(lang);
//		if(dn == null || dn.getText().trim().length()<=0){
//			dn = this.getNames(0, 1).get(0);
//		}
//		if(dn != null){
//			label = dn.getText();
//		}
//		return label;
//	}
	
	
	public DatasetName getName(String lang){
		DatasetName dn = null;
		if(lang == null){
			lang = "en";
		}
		if(this.ds_type.contentEquals(CUSTOM_GENRE)){
			try {
				Connection conn = DBConnectionFactory.getConnection();
				PreparedStatement pstmt = conn.prepareStatement("select name from custom_dataset_label where custom_dataset_id=? and lang=?");
				pstmt.setInt(1, id);
				pstmt.setString(2, lang);
				ResultSet rs = pstmt.executeQuery();
				if(rs.next()){
					dn = new DatasetName(this, rs.getString(1), lang);
				}
				rs.close();
				pstmt.close();
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else if(this.ds_type.contentEquals(URI_GENRE)){
			String name = URIResource.getLabel(id, lang);
			dn = new DatasetName(this, name, lang);
		}
		return dn;
	}
	/**
	 * for building Lucene index
	 * @param start
	 * @param length
	 * @return
	 */
	public ArrayList<DatasetName> getNames(int start, int length){
		ArrayList<DatasetName> nameList = new ArrayList<DatasetName>();
		if(this.ds_type.contentEquals(CUSTOM_GENRE)){
			try {
				Connection conn = DBConnectionFactory.getConnection();
				StringBuffer csql = new StringBuffer("select name,lang from custom_dataset_label where custom_dataset_id=? order by lang");
				if(length>0){
					csql.append(String.format(" limit %d,%d", start, length));
				}
				PreparedStatement cpstmt = conn.prepareStatement(csql.toString());
				cpstmt.setInt(1, id);
				ResultSet rs = cpstmt.executeQuery();
				while(rs.next()){
//					System.out.println("name:"+rs.getString(1)+"|"+rs.getString(2));
					DatasetName dn = new DatasetName(this, rs.getString(1), rs.getString(2));
					if(!nameList.contains(dn)){
						nameList.add(dn);
					}
				}
				rs.close();
				cpstmt.close();
			conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}else if(this.ds_type.contentEquals(URI_GENRE)){
			try {
				ArrayList<String> pname = PropertyList.getNameForIndexProperties();
				boolean flag = false;
				StringBuffer pString = new StringBuffer(" and p in (");
				for(String uri : pname){
					int pid = URIIDCache.getInstance().getURIID(uri, true);
					if(pid>0){
						pString.append("'u"+pid+"',");
						flag = true;
					}
				}
				if(flag){
					pString.replace(pString.length()-1, pString.length(), ")");
					Connection conn = DBConnectionFactory.getConnection();
					StringBuffer csql = new StringBuffer("select o,lang,p from quadruple where s=? and o like 'l%' "+pString.toString());
					if(length>0){
						csql.append(String.format(" limit %d,%d", start, length));
					}
					PreparedStatement cpstmt = conn.prepareStatement(csql.toString());
					cpstmt.setString(1, "u"+id);
					ResultSet rs = cpstmt.executeQuery();
					while(rs.next()){
//						System.out.println(rs.getString(3)+":"+rs.getString(1).substring(1)+":"+rs.getString(2));//====
//						System.out.println("name:"+rs.getString(1)+"|"+rs.getString(2));
						DatasetName dn = new DatasetName(this, rs.getString(1).substring(1), rs.getString(2));
						if(!nameList.contains(dn)){
							nameList.add(dn);
						}
					}
					rs.close();
					cpstmt.close();
					conn.close();
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return nameList;
	}
//	public String getName() {
//		return name;
//	}
	

	/**
	 * for building Lucene index
	 * for custom dataset and uri dataset, only one description in one language
	 * @param datasetType
	 * @param datasetId
	 * @param language
	 * @return
	 */
	public DatasetComment getDescription(String language){
		DatasetComment comment = null;
		if(ds_type.contentEquals(DatasetItem.CUSTOM_GENRE)){
			comment = DatasetComment.getCustomDescriptionItem(id, language);
		}else if(ds_type.contentEquals(DatasetItem.URI_GENRE)){
			comment = DatasetComment.getUriDescriptionItem(id, language);
		}
		return comment;
	}
	/**
	 * if length<0, get all descriptions
	 * @param datasetType
	 * @param datasetId
	 * @param start
	 * @param length
	 * @return
	 */
	public ArrayList<DatasetComment> getDescriptions(int start, int length){
		ArrayList<DatasetComment> comments = new ArrayList<DatasetComment>();
		if(ds_type.contentEquals(DatasetItem.CUSTOM_GENRE)){
			comments = DatasetComment.getCustomDescriptions(id, start, length);
		}else if(ds_type.contentEquals(DatasetItem.URI_GENRE)){
			comments = DatasetComment.getUriDescriptions(id, start, length);
		}
		return comments;
	}
	
	public int getGroupId(){
		if(groupId<0 && ds_type.contentEquals(CUSTOM_GENRE)){
			try {
				Connection conn = DBConnectionFactory.getConnection();
				PreparedStatement pstmt = conn.prepareStatement("select group_id from custom_dataset where id=?");
				pstmt.setInt(1, id);
				ResultSet rs = pstmt.executeQuery();
				if(rs.next()){
					this.groupId = rs.getInt(1);
				}
				rs.close();
				pstmt.close();
				conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		return groupId;
	}
//	public ArrayList<String[]> getDescriptions(String lang){
//		if(this.description == null || this.description.length<2 || !this.description[1].contentEquals(lang)){
//			if(this.genre.contentEquals(CUSTOM_GENRE)){
//				ArrayList<DatasetComment> customdsc = DatasetComment.getCommentsByDatasetLangUserOrderByTime(genre, id, lang, null, 0, -1);
//				this.description = new ArrayList<String[]>();
//				for(DatasetComment dsc : customdsc){
//					
//				}
//			}
//		}
//		return this.description;
//	}
	
//	public void setName(String name){
//		this.name = name;
//	}
	public String toString() {
		return ds_type + "," + id ;//+ "," + name;
	}

	public int hashCode() {
		return toString().hashCode();
	}

	public boolean equals(Object o) {
		if (o == this)
			return true;
		if (!(o instanceof DatasetItem))
			return false;
		DatasetItem that = (DatasetItem) o;
		if (that.toString().equals(this.toString())) {
			return true;
		}
		return false;
	}
}
